#!/usr/bin/python
# -*- coding: utf-8 -*-
import os, sys,time,datetime
import paramiko,configparser

class SshConnectError(Exception):
    pass

class ssh_ctrl:
    def __init__(self,host,username,password,port=22):
        self.host=host
        self.ssh=ssh_ctrl.__sshConn(self.host,username,password,int(port))
        self.sftp=self.__sftpConn()

    def close(self):
        if hasattr(self.ssh,"close"):
            self.ssh.close()

    @staticmethod
    def __sshConn(host,username,password,port):
        ssh=paramiko.SSHClient()   ##创建一个SSH客户端client对象
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(hostname=host,port=int(port),username=username,password=password)
            print("SSH %s 连接成功"%host)
        except:
            raise SshConnectError("SSH Connect %s Error!"% host)
        return ssh

    #返回sftp管道实例对象方法
    def __sftpConn(self):
        transport = self.ssh.get_transport() ##先SSH连上，再建立管道连接
        sftp=paramiko.SFTPClient.from_transport(transport) #创建一个已连通的SFTP客户端通道
        return sftp

    #执行命令方法
    def exeCommand(self,cmd,timeout=300):
        stdin,stdout,stderr=self.ssh.exec_command(cmd,timeout=timeout)
        try:
            channel=stdout.channel
            exit_code=channel.recv_exit_status()
            #报错返回127，没有报错返回0
            stdout=stdout.read().strip()
            stderr=stderr.read().strip()
            return {"status":1,"stdout":stdout,"stderr":stderr,"exit_code":exit_code}
        except:
            return {"status":0,"stdout":stdout,"stderr":stderr,"exit_code":127}

    @staticmethod
    def iter_local_path(abs_path):
        ##遍历本机目录，并返回
        result=set([])
        for path,dirs,files in os.walk(abs_path):
            # print(j)
            # for dir in dirs:
            #     print(dir)
            for file in files:
                file_path=os.path.join(path,file)
                result.add(file_path)
        return result
   
    def iter_remote_path(self,abs_path):
        set_list=set()
        shell_list=self.exeCommand("cd %s;./getdir.sh;cat path.txt"%abs_path)["stdout"].decode(encoding='utf-8').splitlines()
        # print(shell_list)
        for path in shell_list:
            # print(path)
            str_path=os.path.join(abs_path,path).replace(r'\.//','/')
            str_path=str_path.replace(r'\./','/')
            if('.' in str_path):
                set_list.add(str_path)
        # print(set_list)
        return set_list

    #文件上传下载方法
    def sftpFile(self,remotepath,localpath,action):
        try:
            if action =='push':
                # dir=os.path.split(remotepath)[0]
                dir = os.path.dirname(remotepath)
                # print(dir)
                self.exeCommand("mkdir -p %s"%dir)      #根据远程路径新建目录
                self.sftp.put(localpath,remotepath)
                return {"status":1,"message":"sftp %s %s 上传成功！"%(self.host,action)}
            elif action=="pull":
                self.sftp.get(remotepath,localpath)
                return {"status":1,"message":"sftp %s %s 下载成功！"%(self.host,action),"stderr":""}
        except Exception as e:
            return {"status":0,"message":"sftp %s %s 失败！%s"%(self.host,action,str(e)),"stdout":""}

def load_files(host,username,password,remotepath,localpath):
    x=ssh_ctrl(host,username,password)
    local=os.path.join(localpath,'getdir.sh').replace('\\','/')
    remote=os.path.join(remotepath,'getdir.sh').replace('\\','/')
    print(local,remote)
    q =x.sftpFile(localpath=local,remotepath=remote,action="push")
    print(q)
    c=x.exeCommand("cd %s;pwd;whoami;chmod +x getdir.sh"%remotepath)["stdout"].decode(encoding='utf-8').splitlines()
    print(c)
    for i in x.iter_remote_path(remotepath):
        # print(i)
        localp=i.replace(remotepath,localpath)
        localp2=localp.replace('/','\\')
        # count=localp2.rfind('\\')
        dir_list=os.path.split(localp2)[0]
        os.makedirs(dir_list,exist_ok=True)
        print(dir_list)
        p =x.sftpFile(remotepath=i,localpath=localp2,action="pull")
        print(p)
    rm_result=x.exeCommand("cd %s;rm -rf path.txt getdir.sh;echo files download complete!"%remotepath)["stdout"].decode(encoding='utf-8').splitlines()
    print(rm_result)
    x.close()

def upload_files(host,username,password,remotepath,localpath):
    x=ssh_ctrl(host,username,password)
    for l in x.iter_local_path(localpath):
        remote1=l.replace(localpath,remotepath)
        remote1=remote1.replace('\\','/')
        q =x.sftpFile(localpath=l,remotepath=remote1,action="push")
        print(q)
        # print(remote1)
    # b=x.exeCommand("echo device restart.;reboot")["stdout"].decode(encoding='utf-8').splitlines()           ##更新完语音后设备重启
    # print(b)
    x.close()
##遍历本地音频文件路径，拼接字符串路径生成远程路径
##返回zip对象
def path_audio(localpath,remotepath):
    odd_1=[]               #本地单号车语音文件路径列表
    odd_1_remote=[]         #远程单号车语音文件路径列表
    even_2=[]               #本地双号车语音文件路径列表
    even_2_remote=[]        #远程双号车语音文件路径列表
    local_list=list(ssh_ctrl.iter_local_path(localpath))     ##调用类的静态方法，遍历本地语音文件，获取语音文件路径列表
    for i in local_list:
        if('odd_1' in i):         #通过判断odd_1所在字符串获取单号车语音文件路径
            # print(i)
            temp=os.path.basename(i)                             #获取单号车语音文件名
            temp_remote=os.path.join(remotepath,'audio',temp)    #拼接远程单号车语音文件路径
            remot2=temp_remote.replace('\\','/')                  #替换WIN路径中的\为linux路径中的/
            # print(remot2)
            odd_1_remote.append(remot2)                         #将拼接好的单号车远程路径添加到列表中
            odd_1.append(i)                                     #将单号车的本地路径添加到列表中
        if('even_2'in i):
            temp=os.path.basename(i)
            temp_remote=os.path.join(remotepath,'audio',temp)
            remot2=temp_remote.replace('\\','/')
            # print(remot2)
            even_2_remote.append(remot2)
            even_2.append(i)
    # print("odd_1:",odd_1)
    # print("even_2:",even_2)
    # print("odd_1_remote:",odd_1_remote)
    # print("even_2_remote:",even_2_remote)
    l_1=zip(odd_1,odd_1_remote)             #单号车本地路径与远端路径的对应元组
    l_2=zip(even_2,even_2_remote)           #双号车本地路径与远端路径的对应元组
    # print(l_1)

    return(l_1,l_2)

def upload_audio(host,username,password,l_1,l_2,flag):
    x=ssh_ctrl(host,username,password)
    if(flag==1):
        n=x.exeCommand("cd %s;rm -rf audio;echo old audio has removed!"%remotepath)["stdout"].decode(encoding='utf-8').splitlines()
        print(n)
        for i in l_1:
            now=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            print("[{}] start upload.{}  >>>  {}".format(now,i[0],i[1]))
            a=x.sftpFile(remotepath=i[1],localpath=i[0],action='push')
            print(a)
        n=x.exeCommand("cd %s/audio;ls -l |grep '^-'|wc -l"%remotepath)["stdout"].decode(encoding='utf-8').splitlines()
        print(n)
        # n=x.exeCommand("reboot")["stdout"].decode(encoding='utf-8').splitlines()
        # print(n)
    elif(flag==0):
        n=x.exeCommand("cd %s;rm -rf audio;echo old audio has removed!"%remotepath)["stdout"].decode(encoding='utf-8').splitlines()
        print(n)
        for i in l_2:
            now=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")    ##读取当前系统时间
            print("[{}] start upload.{}  >>>  {}".format(now,i[0],i[1]))
            a=x.sftpFile(remotepath=i[1],localpath=i[0],action='push')
            print(a)
        n=x.exeCommand("cd %s/audio;ls -l |grep '^-'|wc -l"%remotepath)["stdout"].decode(encoding='utf-8').splitlines()    #统计文件个数
        print(n)
        # n=x.exeCommand("reboot")["stdout"].decode(encoding='utf-8').splitlines()
        # print(n)
    else:
        print("Some things wrong!") 
if __name__=='__main__':
    
    now=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    conf=configparser.ConfigParser()

    try:
        local_path=os.getcwd()
        local_config=os.path.join(local_path,"config.ini")
        # print(local_config)
        conf.read(local_config)
        host=conf.get('upload','host')
        
        host1=conf.get('upload','host1')
        username=conf.get('upload','username')
        password=conf.get('upload','password')
        port=conf.get('upload','port')
        remotepath=conf.get('upload','remote_path')
        # localpath=conf.get('upload','local_path')
        # local_path=os.getcwd()
    except IOError:
        print("config file can not open!")

    xc=path_audio(local_path,remotepath)
    l_1=xc[0]
    l_2=xc[1]
    num=int(input("请输入增购车实际车号(例如42):"))
    log=os.path.join(local_path,'log.txt')
    try:
        flag=num%2
        upload_audio(host,username,password,l_1,l_2,flag)
        with open(log,'a+') as f:
            f.write(now+'##'+host+'##'+': 更新完语音文件的车号 :'+str(num)+'\n')
    except (IOError,SshConnectError):
        with open(log,'a+') as f:
            f.write(now+'##'+host+'##'+':PCU1设备连接出错语音更新没有完成:'+str(num)+'\n')
        print("Some things wrong!,请检查网线连接及PCU1设备状态")

    xc=path_audio(local_path,remotepath)
    l_1=xc[0]
    l_2=xc[1]
    try:
        flag=num%2
        upload_audio(host1,username,password,l_1,l_2,flag)
        with open(log,'a+') as f:
            f.write(now+'##'+host1+'##'+': 更新完语音文件的车号 :'+str(num)+'\n')
    except (IOError,SshConnectError):
        with open(log,'a+') as f:
            f.write(now+'##'+host1+'##'+': PCU2设备连接出错语音更新没有完成 :'+str(num)+'\n')
        print("Some things wrong!，请检查网线连接及PCU2设备状态")

    
    
   


    
    

















